#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>

// 打开并配置串口（非阻塞模式）
int open_serial(const char *port, int baudrate)
{
    int fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    struct termios tty;
    memset(&tty, 0, sizeof(tty));

    // 读取当前串口配置
    if (tcgetattr(fd, &tty) != 0)
    {
        perror("tcgetattr");
        close(fd);
        return -1;
    }

    // 设置波特率
    cfsetispeed(&tty, baudrate);
    cfsetospeed(&tty, baudrate);

    // 8N1: 8 数据位，无校验，1 停止位
    tty.c_cflag &= ~PARENB;        // 无校验
    tty.c_cflag &= ~CSTOPB;        // 1 停止位
    tty.c_cflag &= ~CSIZE;         // 清除数据位掩码
    tty.c_cflag |= CS8;            // 8 数据位
    tty.c_cflag |= CREAD | CLOCAL; // 使能接收，本地模式

    // 原始模式 - 禁用输入处理、回显等
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tty.c_oflag &= ~OPOST;

    // 关闭流控
    tty.c_cflag &= ~CRTSCTS;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);

    // 设置最小字符数和等待时间（非阻塞下通常设为 0）
    tty.c_cc[VMIN] = 0;  // 读取最小字节数（0 表示立即返回）
    tty.c_cc[VTIME] = 0; // 超时时间（0 表示无超时）

    // 清空输入输出缓冲区
    tcflush(fd, TCIOFLUSH);

    // 应用配置
    if (tcsetattr(fd, TCSANOW, &tty) != 0)
    {
        perror("tcsetattr");
        close(fd);
        return -1;
    }

    printf("Serial port %s opened successfully.\n", port);
    return fd;
}

// 写数据到串口
int serial_write(int fd, const uint8_t *data, int len)
{
    int n = write(fd, data, len);
    if (n < 0)
    {
        perror("write");
        return -1;
    }
    printf("Wrote %d bytes.\n", n);
    return n;
}

// 读取串口数据（非阻塞）
int serial_read(int fd, uint8_t *buf, int max_len)
{
    int n = read(fd, buf, max_len);
    if (n < 0)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            // 没有数据可读，正常情况
            return 0;
        }
        else
        {
            perror("read");
            return -1;
        }
    }
    else if (n == 0)
    {
        printf("No data available.\n");
        return 0;
    }

    printf("Read %d bytes: ", n);
    for (int i = 0; i < n; i++)
    {
        printf("%02X ", buf[i]);
    }
    printf("\n");
    return n;
}

// 关闭串口
void close_serial(int fd)
{
    close(fd);
    printf("Serial port closed.\n");
}

// ================= 主函数示例 =================
int main(int argc, char *argv[])
{
    const char *port = "/dev/tnt0"; // 或 /dev/ttyUSB0, /dev/ttyS0
    int baudrate = B115200;
    if (2 != argc)
    {
        fprintf(stderr, "usage : ./tty_test /dev/ ttyS1");
    }
    int fd = open_serial(argv[1], baudrate);
    if (fd < 0)
    {
        fprintf(stderr, "Failed to open serial port.\n");
        return -1;
    }

    uint8_t send_data[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A}; // Modbus RTU 示例
    uint8_t recv_buf[256];

    // 循环读取（非阻塞）
    for (int i = 0; i < 10000; i++)
    {
        // 可选：发送数据
        if (i % 5 == 0)
        {
            serial_write(fd, send_data, sizeof(send_data));
        }

        // 非阻塞读取
        int len = serial_read(fd, recv_buf, sizeof(recv_buf));
        if (len > 0)
        {
            printf("Received data.\n");
            // 处理数据...
        }

        sleep(1); // 模拟其他任务
    }

    close_serial(fd);
    return 0;
}